#ifndef MOAB_MPE_H
#define MOAB_MPE_H

#include "moab/MOABConfig.h"
#ifdef MOAB_HAVE_LIBMPE
#include "moab_mpi.h"
#include "mpe.h"
#else

/* Define dummy logging functions */

/* mpe_misc.h */

#define MPE_Seq_begin( A, B ) \
    {                         \
        if( ( A ) || ( B ) )  \
        {                     \
        }                     \
    }

#define MPE_Seq_end( A, B )  \
    {                        \
        if( ( A ) || ( B ) ) \
        {                    \
        }                    \
    }

#define MPE_DelTag( A, B, C, D )                   \
    (                                              \
        {                                          \
            if( ( A ) || ( B ) || ( C ) || ( D ) ) \
            {                                      \
            }                                      \
        },                                         \
        MPI_SUCCESS )
#define MPE_GetTags( A, B, C, D ) ( ( A ) = *( C ), *( D ) = 0, if( B ){}, MPI_SUCCESS )
#define MPE_ReturnTags( A, B, C )         \
    (                                     \
        {                                 \
            if( ( A ) || ( B ) || ( C ) ) \
            {                             \
            }                             \
        },                                \
        0 )
#define MPE_TagsEnd() ( MPI_SUCCESS )

#define MPE_IO_Stdout_to_file( A, B ) \
    {                                 \
        if( ( A ) || ( B ) )          \
        {                             \
        }                             \
    }

#define MPE_GetHostName( A, B ) \
    {                           \
        if( ( A ) || ( B ) )    \
        {                       \
        }                       \
    }

#define MPI_Start_debugger()

/*
#if (defined(__STDC__) || defined(__cplusplus))
#define  MPE_Errors_to_dbx ( MPI_Comm *, int *, ... );
#else
void MPE_Errors_to_dbx ( MPI_Comm *, int *, char *, char *, int * );
#endif
void MPE_Errors_call_debugger ( char *, char *, char ** );
void MPE_Errors_call_xdbx     ( char *, char * );
void MPE_Errors_call_dbx_in_xterm ( char *, char * );
void MPE_Signals_call_debugger ( void );

int  MPE_Decomp1d ( int, int, int, int *, int * );

void MPE_Comm_global_rank ( MPI_Comm, int, int * );
*/

/* mpe_log.h */

#define MPE_LOG_OK              0
#define MPE_Log_OK              MPE_LOG_OK
/* no problems */
#define MPE_LOG_LOCKED_OUT      1
#define MPE_Log_LOCKED_OUT      MPE_LOG_LOCKED_OUT
/* logs are being worked on, cannot insert any new entries */
#define MPE_LOG_NO_MEMORY       2
#define MPE_Log_NO_MEMORY       MPE_LOG_NO_MEMORY
/* could not allocate memory for logging data */
#define MPE_LOG_FILE_PROB       3
#define MPE_Log_FILE_PROB       MPE_LOG_FILE_PROB
/* cound not open file for writing out the logged info */
#define MPE_LOG_NOT_INITIALIZED 4
#define MPE_Log_NOT_INITIALIZED MPE_LOG_NOT_INITIALIZED
/* logging not initialized */
#define MPE_LOG_PACK_FAIL       5
#define MPE_Log_PACK_FAIL       MPE_LOG_PACK_FAIL

#define MPE_Init_log()            ( MPI_SUCCESS )
#define MPE_Initialized_logging() 1

#define MPE_Describe_state( A, B, C, D )       \
    {                                          \
        if( ( A ) || ( B ) || ( C ) || ( D ) ) \
        {                                      \
        }                                      \
    }
#define MPE_Describe_event( A, B, C ) \
    {                                 \
        if( ( A ) || ( B ) || ( C ) ) \
        {                             \
        }                             \
    }
#define MPE_Log_get_event_number()
#define MPE_Log_send( A, B, C )       \
    {                                 \
        if( ( A ) || ( B ) || ( C ) ) \
        {                             \
        }                             \
    }
#define MPE_Log_receive( A, B, C )    \
    {                                 \
        if( ( A ) || ( B ) || ( C ) ) \
        {                             \
        }                             \
    }
#define MPE_Log_event( A, B, C )      \
    {                                 \
        if( ( A ) || ( B ) || ( C ) ) \
        {                             \
        }                             \
    }
#define MPE_Start_log()
#define MPE_Stop_log()
#define MPE_Finish_log( A ) \
    {                       \
        if( A )             \
        {                   \
        }                   \
    }

#endif

#ifdef __cplusplus

namespace moab
{

class MPEState
{
  private:
    int sid, eid;
    bool ok;

  public:
    MPEState( const char* name, const char* color = 0 )
        : sid( MPE_Log_get_event_number() ), eid( MPE_Log_get_event_number() ), ok( true )
    {
        MPE_Describe_state( sid, eid, name, color ? color : "yellow" );
    }

    MPEState() : ok( false ) {}
    bool valid() const
    {
        return ok;
    }

    void start( int data = 0, const char* str = 0 )
    {
        MPE_Log_event( sid, data, str );
    }
    void start( const char* str, int data = 0 )
    {
        MPE_Log_event( sid, data, str );
    }
    void start( const char* str, const char* str2 )
    {
        MPE_Log_event( sid, 0, ( std::string( str ).append( str2 ) ).c_str() );
    }
    void end( int data = 0, const char* str = 0 )
    {
        MPE_Log_event( eid, data, str );
    }
    void end( const char* str, int data = 0 )
    {
        MPE_Log_event( eid, data, str );
    }
};

class MPEEvent
{
  private:
    int id;

  public:
    MPEEvent( const char* name, const char* color = 0 ) : id( MPE_Log_get_event_number() )
    {
        MPE_Describe_event( id, name, color ? color : "red" );
    }
    void log( int data = 0, const char* str = 0 )
    {
        MPE_Log_event( id, data, str );
    }
    void log( const char* str, int data = 0 )
    {
        MPE_Log_event( id, data, str );
    }
};

} /* namespace moab */

#endif /* __cplusplus */

#endif /* MOAB_MPE_H */
